// Copyright (c) 2019 Uber Technologies, Inc.
//

import { zoomIdentity } from 'd3-zoom'
const SCALE_MAX = 1
const SCALE_MIN = 0.03
const SCALE_MARGIN = 0.05
const DEFAULT_ZOOM_STYLE = Object.freeze({
  transform: `translate(0px, 0px) scale(1)`,
  transformOrigin: '0 0',
})
export const DEFAULT_SCALE_EXTENT = [SCALE_MIN, SCALE_MAX]
function boundValue(min, max, value) {
  if (value < min) {
    return min
  }
  return value > max ? max : value
}
function getFittedScale(width, height, viewWidth, viewHeight) {
  return Math.max(
    SCALE_MIN,
    Math.min(
      ((1 - SCALE_MARGIN) * viewWidth) / width,
      ((1 - SCALE_MARGIN) * viewHeight) / height,
      SCALE_MAX,
    ),
  )
}
export function getScaleExtent(width, height, viewWidth, viewHeight) {
  const scaleMin = getFittedScale(width, height, viewWidth, viewHeight)
  return [scaleMin, SCALE_MAX]
}
export function fitWithinContainer(width, height, viewWidth, viewHeight) {
  const scale = getFittedScale(width, height, viewWidth, viewHeight)
  const scaledHeight = scale * height
  const scaledWidth = scale * width
  const x = (viewWidth - scaledWidth) / 2
  const y = (viewHeight - scaledHeight) / 2
  return zoomIdentity.translate(x, y).scale(scale)
}
export function constrainZoom(transform, width, height, viewWidth, viewHeight) {
  const { k: tk, x: tx, y: ty } = transform
  const fittedScale = getFittedScale(width, height, viewWidth, viewHeight)
  const k = Math.max(tk, fittedScale)
  const x = boundValue(-width * k + viewWidth * 0.5, viewWidth * 0.5, tx)
  const y = boundValue(-height * k + viewHeight * 0.5, viewHeight * 0.5, ty)
  if (k !== tk || x !== tx || y !== ty) {
    return zoomIdentity.translate(x, y).scale(k)
  }
  return transform
}
export function getZoomStyle(transform) {
  if (transform == null) {
    return DEFAULT_ZOOM_STYLE
  }
  const { x, y, k } = transform
  const rv = {
    transform: `translate(${x.toFixed()}px, ${y.toFixed()}px) scale(${k})`,
    transformOrigin: '0 0',
  }
  return rv
}
export function getZoomAttr(transform) {
  if (!transform) {
    return undefined
  }
  const { x, y, k } = transform
  return `translate(${x.toFixed()},${y.toFixed()}) scale(${k})`
}
